package ui20131001.bMapHelper
{
	import bMap.BMapCanvas;
	
	import baidu.map.basetype.LngLat;
	import baidu.map.core.Map;
	import baidu.map.event.MapEvent;
	import baidu.map.overlay.Marker;
	import baidu.map.overlay.geometry.Polyline;
	import baidu.map.service.convert.Convertor;
	
	import controllers.commands.ParseMobileInfoCommand;
	import controllers.managers.UIInstanceManager;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.utils.Timer;
	import flash.utils.clearTimeout;
	import flash.utils.setTimeout;
	
	import model.filter.ProtocalFilter;
	import model.protocal.GpsInvalid_lbs_protocal;
	import model.protocal.base.IProtocol;
	import model.validator.DeviceUtil;
	
	import ui20131001.DeviceMenuPanel;
	import ui20131001.service.ConvertorCommand;

	/**
	 * 百度地图工具类，包含项目相关的地图操作
	 * @author limin
	 * 
	 */
	public class BMapHelper
	{
		private static var _instance:BMapHelper;
		
		
		public function BMapHelper()
		{
			if ( _instance )
			{
				throw new Error("不能直接实例化.");
			}
		}
		
		public static function getInst():BMapHelper
		{
			if ( _instance == null )
			{
				_instance = new BMapHelper();
			}
			return _instance;
		} 
		
		//------------------------
		private function get maper():Maper
		{
			return UIInstanceManager.getUI(Maper.NAME) as Maper
		}
		
		private function get mapCanvas():BMapCanvas
		{
			return maper.baiMap;
		}
		private function get deviceMenuPanel():DeviceMenuPanel
		{
			return maper.deviceMenuPanel;
		}
		
		/** 坐标转换控件 */
		public function get convertor():Convertor
		{
			return mapCanvas.con;
		}
		
		/** 地图控件 */
		private function get map():Map
		{
			return maper.baiMap.map;
		}
		
		/**
		 * 
		 * @param lngLat
		 * @param option 备用，定义标注属性
		 * 
		 */
		public function setMarker(lngLat:LngLat, option:Object=null):Marker
		{
			//参考MapCanvas同名方法
			return mapCanvas.addMarker(lngLat, option);
		}
		
		public function setLine(bLngLat:LngLat, eLngLat:LngLat):Polyline
		{
			return mapCanvas.addLine(generateLineCoords([bLngLat, eLngLat]));
		}
		
		public function forciblyRefreshMap():void
		{
			mapCanvas.forciblyRefreshMap();
		}
		
		/** 当前位置 */
		public function setCurentLocation(dataData:Object):void
		{
			dataData.map = (dataData.map as Array).filter(ProtocalFilter.doFilterProtocal);
			dataData.sat = (dataData.sat as Array).filter(ProtocalFilter.doFilterProtocal);
			var newData:Object = getLastData(dataData);
			
			var lng:Number = newData.map[0].longitude;
			var lat:Number = newData.map[0].latitude;
			convertPos([new Point(lng, lat)], setCurentLocationConCB);
		}
		
		public function setCurrPosition(lng:Number, lat:Number):void
		{
			convertPos([new Point(lng, lat)], setCurentLocationConCB);
		}
		
		private function setCurentLocationConCB(obj:Object):void
		{
			clearMap();
			var p:Object = obj[0];
			var lngLat:LngLat = new LngLat(p.x, p.y);
			setMarker(lngLat);
			map.panTo(lngLat);
		}
		
		
		/** 
		 * 历史轨迹查询 
		 **/
		public function doQueryHistoryTracker(data:Object):void
		{
			var pArr:Array = [];
			var lng:Number, lat:Number, i:int;
			var len:int = data.map.length;
			for(i=0; i<len; ++i)
			{
				lng = data.map[i].longitude;
				lat = data.map[i].latitude;
				pArr.push(new Point(lng, lat));
			}
			convertPos(pArr, doQueryHistoryTrackerConCB);
		}
		
		private function doQueryHistoryTrackerConCB(arr:Array):void
		{
			clearMap();
			//画线
			var len:int = arr.length;
			drawLine(arr);
			forciblyRefreshMap();
			var lastPoint:Object = arr[len-1];
			map.panTo(new LngLat(lastPoint.x, lastPoint.y));
		}
		
		//批量画线方法，可统一控制线的可见性
		private function drawLine(arr:Array, vis:Boolean=true):Array
		{
			var i:int, p1:Object, p2:Object,line:Polyline;
			var len:int = arr.length;
			var lines:Array = [];
			for(i=1; i<len; ++i)
			{
				p1 = arr[i-1];
				p2 = arr[i];
				line = setLine(new LngLat(p1.x, p1.y), new LngLat(p2.x, p2.y));
				line.visible = vis;
				lines.push(line);
			}
			return lines;
		}
		
		
		private var isPlayback:Boolean = false;
		private var effectIndex:int;
		/** 轨迹回放的数据源 */		
		private var totalPositionObject:Object;
		/**
		 * 轨迹回放
		 **/
		public function playbackPath(dataObj:Object):void
		{
			/*
			 * 回放分为2步：显示路径，移动icon
			*/
			isPlayback = true;
			//清理
			clearMap();
			//重置
			effectIndex = 0;
			
			if(totalPositionObject && dataObj.map.length == 1
				&& totalPositionObject.map.length == 1 && dataObj.map[0].client_id == totalPositionObject.map[0].client_id)
			{
				totalPositionObject = dataObj;
				playDataByType(true,false);
			}else
			{
				totalPositionObject = dataObj;
				playDataByType(true);
			}
		}
		
		/** 轨迹回放的点列表 */
		private var positionArray:Array;
		/** 轨迹回放的线列表 */
		private var lineArray:Array;
		/** 轨迹回放的 方向标志列表 */
		private var directionMarkerArray:Array;
		/** 轨迹回放的icon */
		private var pointIcon:Marker;
		private var pointMC:MovieClip;
		private function playDataByType(isRestart:Boolean=false,isClear:Boolean=true):void
		{
			_isRestart = isRestart;
			_isClear = isClear;
			
			positionArray = totalPositionObject.map;//baidu只使用map坐标做转换
			positionArray = positionArray.filter(isProtocolFilter);
			
			//此处加入定位数据无效时的处理
			getGpsInvalideList();
			
			if(_gpsInvalideList.length>0)
			{
				gpsInvalideLbsHandle()
			}else
			{
				doDrawLocPolyLine();
			}
		}
		
		/** GPS无效的点列表 */
		private var _gpsInvalideList:Array;
		/** 得到GPS无效的点列表 */
		private function getGpsInvalideList():void
		{
			_gpsInvalideList = [];
			var locInfo:Object;
			for each(locInfo in positionArray)
			{
				if ( locInfo.personal_status==0 ) {
					//记录无效对象
					if(parseInt(locInfo.station_info, 16)==0 && (DeviceUtil.getDeviceType()==7 
						|| DeviceUtil.getDeviceType()==18))
					{
						continue;
					}else
					{
						_gpsInvalideList.push(locInfo);
					}
				} 
			}
		}
		
		private var _isRestart:Boolean;
		private var _isClear:Boolean;
		private function doDrawLocPolyLine():void
		{
			//把positionArray坐标全部转换掉
			var pArr:Array = [];
			var lng:Number, lat:Number, i:int;
			var len:int = positionArray.length;
			for(i=0; i<len; ++i)
			{
				lng = positionArray[i].longitude;
				lat = positionArray[i].latitude;
				pArr.push(new Point(lng, lat));
			}
			convertPos(pArr, doDrawLocPolyLineConCB);
		}
		
		private function doDrawLocPolyLineConCB(arr:Array):void
		{
			var i:int, obj:Object;
			var len:int = positionArray.length;
			for(i=0; i<len; ++i)
			{
				obj = positionArray[i];
				obj.x = arr[i].x;
				obj.y = arr[i].y;
			}
			startPositionEffect(_isClear);
		}
		
		//画方向标志
		private function drawDirectionMarker(arr:Array, vis:Boolean=true):Array
		{
			var i:int, p1:Object, marker:Marker, icon:MovieClip;
			var len:int = arr.length;
			var markerArr:Array = [];
			for(i=1; i<len; ++i)
			{
				p1 = arr[i-1];
				icon = new MovieClip();
				var option:Object = {};
				option.icon = icon;
				marker = setMarker(new LngLat(p1.x, p1.y), option);
				marker.visible = vis;
				markerArr.push(marker);
				icon.addChild(getDirectitonMc(p1));
			}
			return markerArr;
		}
		
		private function getDirectitonMc(obj:Object):MovieClip
		{
			var mc:MovieClip;
			var str:String = obj.status_text[0];
			if(str==Global.ACC_CLOSE_STR)
			{
				mc = new DirectionMc_r();
			}else if(str==Global.ACC_OPEN_STR && int(obj.speed)==0)
			{
				mc = new DirectionMc_y();
			}else
			{
				mc = new DirectionMc_g();
			}
			mc.rotation = obj.direction-90;
			return mc;
		}
		
		private var isPlayingMove:Boolean;
		private function startPositionEffect(isClear:Boolean=true):void
		{
			trace("startPositionEffect");
			if(isPlayingMove)
			{
				stopPositionEffect();
			}
			
			isPlayingMove = true;
			//画全部的线
			
			lineArray = drawLine(positionArray, false);
			directionMarkerArray = drawDirectionMarker(positionArray, false);
			//pointMC.rotation = currentPositionData.direction;
			forciblyRefreshMap();
			
			//timers
			initTimers();
			timer.start();
			
			//图标
			mapCanvas.clearPointMc();
			pointMC = new MovieClip();
			var option:Object = {};
			option.icon = pointMC;
			var lngLat:LngLat = new LngLat(positionArray[0].x, positionArray[0].y);
			pointIcon = setMarker(lngLat, option);
			
			pointMC.addChild(getPointMc());
		}
		
		public var carMC:MovieClip = new car;
		public var manMC:MovieClip = new man;
		public var dogMC:MovieClip = new dog;
		private function getPointMc():MovieClip
		{
			switch(int(totalPositionObject.display_id))
			{
				case 1:
					return carMC;
				case 2:
					return manMC;
				case 3:
					return dogMC;
				default:
					return carMC;
			}
		}
		
		private var timer:Timer;
		private var actionTimer:Timer;
		private function initTimers():void
		{
			if(!timer)
			{
				timer = new Timer(50);
				timer.addEventListener(TimerEvent.TIMER,onEffect);
			}
			if(!actionTimer)
			{
				actionTimer = new Timer(50 + Global.playSpeed*100,5);
				actionTimer.addEventListener(TimerEvent.TIMER,onEffectAction);
				actionTimer.addEventListener(TimerEvent.TIMER_COMPLETE,onEffectActionComplete);
			}
		}
		
		/**
		 * 轨迹动画播放结束
		 */
		private function stopPositionEffect():void
		{
			isPlayback = false;
			resetAll();
			if(endPositionData)
			{
				createMarkerWhenEnd();
//				locationManager.query( currentPositionData.latitude + "," + currentPositionData.longitude);	
			}
			endPositionData = null;
			startPositionData = null;
		}
		
		/**
		 * 结束动画，添加Marker
		 **/
		private function createMarkerWhenEnd():void
		{
			if(endPositionData != null)
			{
				var lngLat:LngLat = new LngLat(endPositionData.x, endPositionData.y);
				setMarker(lngLat);
			}
		}
		
		/**
		 * 重置资源
		 */
		public function resetAll():void
		{
			timer.stop();
			actionTimer.stop();
			
			isPlayingMove = false;
			mapCanvas.clearPointMc();
		}
		
		private var endPositionData:Object;
		private var startPositionData:Object;
		private var isPause:Boolean;
		/** 画轨迹线 */		
		private function onEffect(e:Event=null):void
		{
			if(isPause)
			{
				timer.stop();
				return;
			}
			
			if(effectIndex < positionArray.length)
			{
				if(endPositionData)
				{
					startPositionData = endPositionData;
				}
				
				endPositionData = positionArray[effectIndex];
				
				if(startPositionData)
				{
					var line:Polyline = lineArray[effectIndex-1];
					line.visible = true;
					var marker:Marker = directionMarkerArray[effectIndex-1];
					marker.visible = true;
					
					//此条件过滤连续相同坐标点的情况
					if(endPositionData.x!=startPositionData.x 
						|| endPositionData.y!=startPositionData.y)
					{
						map.panTo(new LngLat(endPositionData.x, endPositionData.y));
						timeToStartActionTimer();
					}
				}else
				{
					startPositionData = endPositionData;
					map.panTo(new LngLat(endPositionData.x, endPositionData.y));
					timeToStartActionTimer();
				}
				
				effectIndex ++;
			}else
			{
				stopPositionEffect();
			}
		}
		
		private var startActionTimeout:uint;
		private function timeToStartActionTimer(delay:Number=0):void
		{
			clearTimeout(startActionTimeout);
			
			timer.stop();
			if(delay==0)
			{
				startActionTimer();
			}else
			{
				startActionTimeout = setTimeout(startActionTimer, 1000);
			}
		}
		
		private function startActionTimer():void
		{
			clearTimeout(startActionTimeout);
			if(isPlayingMove && startPositionData && endPositionData)
			{
				actionTimer.reset();
				actionTimer.start();
			}
		}
		
		private function onEffectAction(e:Event=null):void
		{//分5次移动图标
			var n:Number = actionTimer.currentCount/actionTimer.repeatCount;
			var x:Number = startPositionData.x+(endPositionData.x-startPositionData.x)*n;
			var y:Number = startPositionData.y+(endPositionData.y-startPositionData.y)*n;
			pointIcon.position = new LngLat(x, y);
		}
		
		private function onEffectActionComplete(e:Event=null):void
		{
			timer.start();
		}
		
		//GPS无效处理
		private function gpsInvalideLbsHandle():void
		{
			Global.openLoading();
			
			var locInfo:Object;
			for each(locInfo in _gpsInvalideList)
			{
				var stationInfo:String = locInfo.station_info;
				var prex:int = 4;
				var endx:int = 4;
				var len:int = stationInfo.length;
				var lac:String = Number("0x" + stationInfo.substr(0, prex)).toString(10);
				var cid:String = Number("0x" + stationInfo.substr(endx, len)).toString(10);
				var protocal:IProtocol = new GpsInvalid_lbs_protocal(lac, cid, locInfo, gpsInvalidLbsCallback);
				var parser:ParseMobileInfoCommand = new ParseMobileInfoCommand(protocal);
				parser.execute();
			}
		}
		private function gpsInvalidLbsCallback(data:Object):void
		{
			var i:int, locInfo:Object;
			var len:int = _gpsInvalideList.length;
			for(i=0; i<len; ++i)
			{
				locInfo = _gpsInvalideList[i];
				if(data==locInfo)
				{
					//处理好了的点移除
					_gpsInvalideList.splice(i, 1);
				}
			}
			if(_gpsInvalideList.length==0)
			{
				Global.hideLoading();
				doDrawLocPolyLine();
			}
		}
		
		private function isProtocolFilter(element:Object, index:int, arr:Array):Boolean
		{
			return ProtocalFilter.doFilterProtocal(element,index,arr);
		}
		
		
		//---------------------------------
		private function getLastData(data:Object):Object
		{
			var newData:Object = {};
			newData.map = [data.map[data.map.length - 1] ];
			newData.sat = [data.sat[data.sat.length - 1] ];
			return newData;
		}
		
		private function clearMap():void
		{
			map.clearOverlays();
		}
		
		private function convertPos(arr:Array, callback:Function):ConvertorCommand
		{
			var conCmd:ConvertorCommand = new ConvertorCommand(callback);
			conCmd.execute(arr);
			return conCmd;
		}
		
		/**
		 * @param arr [LngLat(116.36, 39.860), LngLat(116.405, 39.920)]
		 * @return 
		 */
		public function generateLineCoords(arr:Array):Vector.<LngLat>
		{
			var coords:Vector.<LngLat> = new Vector.<LngLat>();
			var i:int;
			var len:int = arr.length;
			for(i=0; i<len; ++i)
			{
				coords.push(arr[i]);
			}
			return coords;
		}
		
		public function playButton_clickHandler():void
		{
			if(BMapHelper.getInst().isPlayingMove && BMapHelper.getInst().timer)
			{
				isPause = false;
				isPlayback = true;
				timer.start();
				setPlayButtonEnable(false);
			}
		}
		
		private function setPlayButtonEnable(value:Boolean):void
		{
			mapCanvas.pauseButton.mouseEnabled = !value;
			mapCanvas.pauseButton.visible = !value;
			mapCanvas.pauseButton.buttonMode = !value;
			
			mapCanvas.playButton.mouseEnabled = value;
			mapCanvas.playButton.visible = value;
			mapCanvas.playButton.buttonMode = value;
		}
		
		public function pauseButton_clickHandler():void
		{
			if(isPlayingMove && timer)
			{
				isPause = true;
				isPlayback = false;
				setPlayButtonEnable(true);
			}
		}
		
		public function hslider1_changeHandler(s:Number):void
		{
			Global.playSpeed = s;
			if(actionTimer)
			{
				actionTimer.delay = 50 + Global.playSpeed*100;
				actionTimer.repeatCount = 5;
			}
		}
		
		public function refreshControlPos():void
		{
			var w:int = deviceMenuPanel.opened ? 90 : 0;
			mapCanvas.refreshControlPos(w, 0);
		}
		
	}
}